package cn.com.longfuinfo.wx.controller;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.bind.JAXBException;

import org.apache.log4j.Logger;

import cn.com.longfuinfo.api.bean.EventMessage;
import cn.com.longfuinfo.api.bean.xmlmessage.XMLMessage;
import cn.com.longfuinfo.wx.common.Constants;
import cn.com.longfuinfo.wx.common.FinalParam;
import cn.com.longfuinfo.wx.exception.SaveException;
import cn.com.longfuinfo.wx.service.UserService;
import cn.com.longfuinfo.wx.util.ExpireSet;
import cn.com.longfuinfo.wx.util.SignatureUtil;
import cn.com.longfuinfo.wx.util.XMLConverUtil;

public class ReceiveAction extends HttpServlet {
	private Logger log = Logger.getLogger(this.getClass());
	private UserService userService = new UserService();
	private static final long serialVersionUID = 1L;

	// 从官方获取
	private static String token = FinalParam.Token;

	// 重复通知过滤 时效60秒
	private static ExpireSet<String> expireSet = new ExpireSet<String>(60);

	// 中控管理类， 分发微信服务器传过来的事件处理
	private WxEventControlManager wecm = new WxEventControlManager();
	private XMLMessage xmlMessage;// 回复的消息

	protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
		log.info("进入微信公众号，接受消息回调函数！");
		request.setCharacterEncoding("UTF-8");
		ServletInputStream inputStream = request.getInputStream();

		ServletOutputStream outputStream = response.getOutputStream();
		String signature = request.getParameter("signature");
		String timestamp = request.getParameter("timestamp");
		String nonce = request.getParameter("nonce");
		String echostr = request.getParameter("echostr");

		// 首次请求申请验证,返回echostr
		if (echostr != null) {
			log.info("首次请求申请验证..");
			outputStreamWrite(outputStream, echostr);
			return;
		}

		// 验证请求签名
		if (!signature.equals(SignatureUtil.generateEventMessageSignature(token, timestamp, nonce))) {
			log.info(token);
			log.info("请求签名无效..");
			return;
		}
		log.info("请求签名有效..继续前行");
		if (inputStream != null) {
			try {
				// 转换XML 接受消息对象
				EventMessage eventMessage = XMLConverUtil.convertToObject(
						EventMessage.class, inputStream);
				String expireKey = eventMessage.getFromUserName() + "__"
						+ eventMessage.getToUserName() + "__"
						+ eventMessage.getMsgId() + "__"
						+ eventMessage.getCreateTime();

				if (expireSet.contains(expireKey)) { // 重复通知不作处理
					return;
				} else {
					expireSet.add(expireKey);
				}

				log.info("发送方账号："+eventMessage.getFromUserName());
				HttpSession session = request.getSession();
				session.setAttribute(Constants.WX_USER, userService.findByOpenid(eventMessage.getFromUserName()));
				xmlMessage = wecm.contorlEvent(eventMessage);
				if (xmlMessage == null) {// 事件推送过来之后,不进行回复消息
					log.error("xmlMessage为null===========>");
					outputStreamWrite(outputStream, "");
					return;
				}
				// 回复消息
				xmlMessage.outputStreamWrite(outputStream);
			} catch (SaveException e) {
				log.error("微信处理信息报错 : " + e.getMessage());
				outputStreamWrite(outputStream, "");
			} catch (JAXBException e) {
				log.error("微信处理信息报错 : 解析用户发送信息错误");
				outputStreamWrite(outputStream, "");
			}
			return;
		}
		outputStreamWrite(outputStream, "");
	}

	@Override
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

	/**
	 * 数据流输出
	 * 
	 * @param outputStream
	 * @param text
	 * @return
	 */
	private boolean outputStreamWrite(ServletOutputStream outputStream,
			String text) {
		try {
			outputStream.write(text.getBytes("utf-8"));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
}
